import sys
import numpy as np
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QHBoxLayout, QGroupBox, QLabel, QLineEdit,
                             QPushButton, QComboBox, QSpinBox, QCheckBox,
                             QFormLayout, QTabWidget, QProgressBar, QSplitter,
                             QTableWidget, QTableWidgetItem, QHeaderView,
                             QGridLayout)
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QColor
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.patches import Rectangle
from CFDSolver import CFDSolver, RectangularMesh
import random
import time
import platform

# 配置Matplotlib使用支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun']
plt.rcParams['axes.unicode_minus'] = False
mpl.rcParams['font.family'] = 'sans-serif'

class SimulationSystem(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('GPU机箱流场仿真系统 - 精确实现')
        self.setGeometry(300, 300, 1400, 900)
        self.setup_ui()
        self.setup_styles()
        self.setup_connections()
        self.simulation_data = {}

        # 设置默认参数
        self.inlet_velocity.setText("1.0")
        self.inlet_temp.setText("298.0")
        self.cpu_power.setText("200")
        self.gpu_power.setText("150")

    def setup_ui(self):
        # 主窗口部件
        main_widget = QWidget()
        main_layout = QHBoxLayout(main_widget)

        # 左侧控制面板
        control_panel = self.create_control_panel()

        # 右侧面板（带标签页）
        right_panel = self.create_right_panel()

        # 使用分割器
        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(control_panel)
        splitter.addWidget(right_panel)
        splitter.setSizes([350, 1050])

        main_layout.addWidget(splitter)
        self.setCentralWidget(main_widget)

    def create_control_panel(self):
        """创建左侧控制面板"""
        panel = QGroupBox("仿真控制")
        panel.setMinimumWidth(350)
        layout = QVBoxLayout()

        # 参数设置
        param_group = QGroupBox("物理参数")
        param_layout = QFormLayout()
        self.inlet_velocity = QLineEdit()
        self.inlet_temp = QLineEdit()
        self.cpu_power = QLineEdit()
        self.gpu_power = QLineEdit()
        param_layout.addRow("入口速度 (m/s):", self.inlet_velocity)
        param_layout.addRow("入口温度 (K):", self.inlet_temp)
        param_layout.addRow("CPU功率 (W):", self.cpu_power)
        param_layout.addRow("GPU功率 (W):", self.gpu_power)
        param_group.setLayout(param_layout)

        # GPU配置
        gpu_group = QGroupBox("GPU阵列精确配置")
        gpu_layout = QVBoxLayout()

        # 添加精确配置说明
        config_info = QLabel("<b>严格按照图纸尺寸实现:</b>")
        config_info.setStyleSheet("color: #1e40af; font-weight: bold;")

        config_details = QLabel(
            "✓ 阵列区域宽度: 32cm\n"
            "✓ 阵列区域高度: 35cm\n"
            "✓ GPU插槽位置: 距离阵列区域顶部3cm\n"
            "✓ 阵列区域左边界: 右移10cm\n"
            "✓ 左边第一GPU位置: 距左边界3.6cm\n"
            "✓ GPU间隔: 2mm\n"
            "✓ 出风口: 4cm"
        )
        config_details.setStyleSheet("color: #047857; font-size: 10pt;")

        gpu_layout.addWidget(config_info)
        gpu_layout.addWidget(config_details)

        # 槽位配置标题
        gpu_layout.addWidget(QLabel("\n安装GPU槽位:"))

        # 槽位布局 - 单行连续排列
        slot_container = QWidget()
        slot_layout = QGridLayout(slot_container)
        slot_layout.setSpacing(5)

        self.slot_checkboxes = []

        # 创建8个槽位的复选框
        for slot in range(8):
            row = slot // 4
            col = slot % 4
            checkbox = QCheckBox(f"槽位{slot+1}")
            checkbox.setChecked(True)
            slot_layout.addWidget(checkbox, row, col)
            self.slot_checkboxes.append(checkbox)

        gpu_layout.addWidget(slot_container)

        # 添加GPU数量显示
        self.gpu_count_label = QLabel("已安装GPU数量: 8")
        self.gpu_count_label.setStyleSheet("background-color: #e5e7eb; padding: 5px; border-radius: 4px;")
        gpu_layout.addWidget(self.gpu_count_label)

        gpu_group.setLayout(gpu_layout)

        # 算法选择
        algo_group = QGroupBox("求解算法")
        algo_layout = QVBoxLayout()
        self.algo_combo = QComboBox()
        self.algo_combo.addItems(["SIMPLE", "PISO", "SIMPLEC"])
        algo_layout.addWidget(QLabel("选择算法:"))
        algo_layout.addWidget(self.algo_combo)
        algo_group.setLayout(algo_layout)

        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setFormat("准备仿真...")

        # 控制按钮
        button_layout = QHBoxLayout()
        self.run_button = QPushButton("开始仿真")
        self.run_button.setFixedHeight(40)
        self.export_button = QPushButton("导出结果")
        self.export_button.setFixedHeight(40)
        button_layout.addWidget(self.run_button)
        button_layout.addWidget(self.export_button)

        # 组装控制面板
        layout.addWidget(param_group)
        layout.addWidget(gpu_group)
        layout.addWidget(algo_group)
        layout.addWidget(self.progress_bar)
        layout.addLayout(button_layout)
        panel.setLayout(layout)

        return panel

    def create_right_panel(self):
        """创建右侧面板"""
        panel = QWidget()
        layout = QVBoxLayout(panel)

        # 标签页控件
        self.tab_widget = QTabWidget()

        # 标签页1: 原型模型
        model_tab = QWidget()
        model_layout = QVBoxLayout(model_tab)
        model_layout.setContentsMargins(5, 5, 5, 5)

        # 创建模型展示区域
        self.model_canvas = FigureCanvas(plt.Figure(figsize=(10, 10)))
        model_layout.addWidget(self.model_canvas)
        self.draw_model()

        # 标签页2: 仿真结果
        result_tab = QWidget()
        result_layout = QVBoxLayout(result_tab)
        result_layout.setContentsMargins(5, 5, 5, 5)

        # 创建结果展示区域
        self.result_canvas = FigureCanvas(plt.Figure(figsize=(10, 8)))
        result_layout.addWidget(self.result_canvas)

        # 标签页3: 温度数据
        data_tab = QWidget()
        data_layout = QVBoxLayout(data_tab)
        data_layout.setContentsMargins(5, 5, 5, 5)

        # 创建温度数据表格
        self.temp_table = QTableWidget()
        self.temp_table.setColumnCount(4)
        self.temp_table.setHorizontalHeaderLabels(["组件", "位置", "温度(℃)", "状态"])
        self.temp_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.temp_table.verticalHeader().setVisible(False)
        data_layout.addWidget(self.temp_table)

        # 添加标签页
        self.tab_widget.addTab(model_tab, "原型模型")
        self.tab_widget.addTab(result_tab, "仿真结果")
        self.tab_widget.addTab(data_tab, "温度数据")

        # 添加到布局
        layout.addWidget(self.tab_widget)

        return panel

    def draw_model(self):
        """根据图纸精确绘制机箱模型"""
        fig = self.model_canvas.figure
        fig.clear()
        ax = fig.add_subplot(111)
        ax.set_aspect('equal')

        # 设计图参数 (单位:厘米)
        # 机箱尺寸
        cabinet_width = 42.0    # 机箱水平宽度
        cabinet_height = 69.0   # 机箱垂直高度

        # 风扇区域
        fan_height = 0.0        # 风扇区域高度
        fan_y = cabinet_height  # 风扇区域y坐标

        # CPU散热器参数
        cpu_top_offset = fan_height + 9.0  # 风扇下方9cm
        cpu_height = 7.0        # CPU散热器高度
        cpu_width = 9.0          # CPU散热器宽度
        cpu_margin = 6.0         # CPU距机箱边界距离

        # GPU阵列区域参数
        gpu_array_height = 35.0  # GPU阵列区域高度
        gpu_array_top = fan_height+ 34.0  # 距离风扇区域下方34cm

        # 精确计算GPU位置
        gpu_width_size = 2.0     # 每个GPU宽度
        gpu_height_size = 28.0   # 每个GPU高度
        gpu_spacing = 0.2         # GPU间隔2mm

        # 计算GPU阵列位置
        gpu_array_left = 10.0    # 左边界右移10cm
        gpu_array_width = 32.0   # GPU阵列区域宽度

        # 绘制机箱轮廓
        cabinet = Rectangle((0, 0), cabinet_width, cabinet_height,
                            fill=False, edgecolor='#1e40af', linewidth=2)
        ax.add_patch(cabinet)

        # 标注机箱尺寸
        '''
        self.add_dimension_annotation(ax, 0, 0, cabinet_width,
                                    f"机箱宽度: {cabinet_width}cm", 'horizontal', offset=3)
        self.add_dimension_annotation(ax, 0, 0, cabinet_height,
                                    f"机箱高度: {cabinet_height}cm", 'vertical', offset=5)
        '''
        # 绘制风扇区域 (冷空气入口)
        fan_line = plt.Line2D([0, cabinet_width], [cabinet_height, cabinet_height],
                            linewidth=3, color='blue')
        '''
        ax.add_line(fan_line)
        ax.text(cabinet_width/2, cabinet_height - 1, "风扇区域 (冷空气入口)",
                ha='center', va='bottom', fontsize=10, color='blue')

        # 添加风扇位置标注
        self.add_dimension_annotation(ax, 0, cabinet_height, 9,
                                    "9cm", 'vertical', offset=-1)
        '''
        # 绘制CPU散热器 (两个)
        # 左侧CPU
        cpu_left = Rectangle((cpu_margin, cabinet_height - cpu_top_offset),
                             cpu_width, -cpu_height,  # 负高度表示向下绘制
                            fill=True, color='#fecaca', alpha=0.8, edgecolor='#b91c1c')

        ax.add_patch(cpu_left)
        ax.text(cpu_margin + cpu_width/2, cabinet_height - cpu_top_offset - cpu_height/2,
                "CPU散热器", ha='center', va='center', fontsize=9, color='#b91c1c')

        # 右侧CPU
        cpu_right_x = cabinet_width - cpu_margin - cpu_width
        cpu_right = Rectangle((cpu_right_x, cabinet_height - cpu_top_offset),
                             cpu_width, -cpu_height,  # 负高度表示向下绘制
                             fill=True, color='#fecaca', alpha=0.8, edgecolor='#b91c1c')

        ax.add_patch(cpu_right)
        ax.text(cpu_right_x + cpu_width/2, cabinet_height - cpu_top_offset - cpu_height/2,
                "CPU散热器", ha='center', va='center', fontsize=9, color='#b91c1c')


        # 添加CPU尺寸标注
        '''
        self.add_dimension_annotation(ax, cpu_margin, cabinet_height - cpu_top_offset,
                                    cpu_width, "9cm", 'horizontal', offset=-2)
        self.add_dimension_annotation(ax, cpu_right_x, cabinet_height - cpu_top_offset,
                                    cpu_width, "9cm", 'horizontal', offset=-2)
        '''
        # 添加CPU位置标注
        '''
        ax.text(cpu_margin/2, cabinet_height - cpu_top_offset - cpu_height/2, "距边界6cm",
                ha='center', va='center', fontsize=8, color='#6b7280', rotation=90)
        ax.text(cabinet_width - cpu_margin/2, cabinet_height - cpu_top_offset - cpu_height/2, "距边界6cm",
                ha='center', va='center', fontsize=8, color='#6b7280', rotation=-90)
        '''
        # 添加GPU阵列位置标注
        self.add_dimension_annotation(ax, 0, cabinet_height,
                                    cabinet_height - (cabinet_height - gpu_array_top),
                                    "34cm", 'vertical', offset=-2)

        # 绘制GPU阵列区域背景
        gpu_array = Rectangle((gpu_array_left, cabinet_height - gpu_array_top),
                             gpu_array_width, -gpu_array_height,  # 负高度表示向下绘制
                             fill=False, edgecolor='#dc2626', linewidth=1.5, linestyle='-')
        ax.add_patch(gpu_array)

        # 添加GPU阵列标签

        ax.text(gpu_array_left + gpu_array_width/2,
               cabinet_height - gpu_array_top - gpu_array_height/2,
                "GPU阵列区域", ha='center', va='center', fontsize=10, color='#dc2626')

        # 添加GPU阵列尺寸标注
        '''
        self.add_dimension_annotation(ax, gpu_array_left, cabinet_height - gpu_array_top,
                                    gpu_array_width, "32cm", 'horizontal', offset=-3)
        self.add_dimension_annotation(ax, gpu_array_left, cabinet_height - gpu_array_top,
                                    -gpu_array_height, "35cm", 'vertical', offset=1)
        '''
        # 添加GPU阵列内部标注

        gpu_slot_start_y = cabinet_height - gpu_array_top - 3.0  # 距阵列区域顶部3cm

        # 绘制GPU槽位区域
        gpu_slots = Rectangle((gpu_array_left + 3.6, gpu_slot_start_y),
                             gpu_array_width - 3.6 - 0.1, -gpu_height_size,
                             fill=False, edgecolor='#047857', linewidth=1, linestyle='--')
        ax.add_patch(gpu_slots)
        '''
        # 添加槽位区域标注
        ax.text(gpu_array_left + gpu_array_width/2, gpu_slot_start_y - gpu_height_size/2,
                "GPU插槽区域", ha='center', va='center', fontsize=9, color='#047857')

        # 添加槽位区域尺寸标注
        self.add_dimension_annotation(ax, gpu_array_left + 3.6, gpu_slot_start_y,
                                    gpu_array_width - 3.6 - 0.1, "32cm-3.7cm=28.3cm",
                                    'horizontal', offset=-4)
        self.add_dimension_annotation(ax, gpu_array_left + gpu_array_width,
                                    cabinet_height - gpu_array_top,
                                    -gpu_array_height, "35cm",
                                    'vertical', offset=1)

        # 添加阵列区域左移标注
        ###
        ax.annotate('左边界右移10cm',
                   xy=(gpu_array_left, cabinet_height/2),
                   xytext=(5, cabinet_height/2),
                   arrowprops=dict(arrowstyle="->", color='#1e40af', linewidth=1),
                   ha='right', va='center', fontsize=8, color='#1e40af')

        # 添加顶部距离标注
        top_offset_line = plt.Line2D([gpu_array_left, gpu_array_left + gpu_array_width],
                                    [gpu_slot_start_y, gpu_slot_start_y],
                                    linewidth=0.5, linestyle=':', color='#6b7280')
        ax.add_line(top_offset_line)
        ax.text(gpu_array_left + gpu_array_width/2, gpu_slot_start_y + 0.5,
                "GPU插槽距阵列区域顶部3cm", ha='center', va='bottom', fontsize=8, color='#6b7280')

        # 添加底部出风口标注
        outlet_line = plt.Line2D([gpu_array_left, gpu_array_left + gpu_array_width],
                               [cabinet_height - gpu_array_top - gpu_array_height,
                                cabinet_height - gpu_array_top - gpu_array_height],
                               linewidth=1, linestyle='-', color='#3b82f6')
        ax.add_line(outlet_line)
        ax.text(gpu_array_left + gpu_array_width/2,
               cabinet_height - gpu_array_top - gpu_array_height + 0.5,
                "底部出风口4cm", ha='center', va='bottom', fontsize=8, color='#3b82f6')
        '''
        # 绘制8个GPU槽位
        gpu_start_x = gpu_array_left + 3.6  # 左边第一块GPU距左边界3.6cm
        gpu_count = 8

        # 计算GPU位置
        for i in range(gpu_count):
            # 计算GPU位置
            gpu_x = gpu_start_x + i * (gpu_width_size + gpu_spacing)

            # GPU位置
            gpu_position = (gpu_x, gpu_slot_start_y)
            gpu_size = (gpu_width_size, -gpu_height_size)  # 负高度表示向下

            # 绘制GPU槽位
            slot = Rectangle(gpu_position, gpu_size[0], gpu_size[1],
                            fill=True, color='#d1d5db', alpha=0.6)
            ax.add_patch(slot)

            # 在已安装的槽位上绘制GPU
            if self.slot_checkboxes[i].isChecked():
                gpu = Rectangle(gpu_position, gpu_size[0], gpu_size[1],
                               fill=True, color='#a7f3d0', alpha=0.8)
                ax.add_patch(gpu)

                # 显示GPU编号
                ax.text(gpu_x + gpu_width_size/2, gpu_slot_start_y - gpu_height_size/2,
                        f"GPU{i+1}", ha='center', va='center', fontsize=8, color='#065f46')
            '''
            # 显示槽位编号
            ax.text(gpu_x + gpu_width_size/2, gpu_slot_start_y,
                    f"槽位{i+1}", ha='center', va='bottom', fontsize=7, color='#4b7280')

            # 添加GPU尺寸标注
            if i == 0:
                # 左边第一块GPU位置标注
                self.add_dimension_annotation(ax, gpu_array_left, gpu_slot_start_y,
                                             3.6, "3.6cm", 'horizontal', offset=-2)

            # 添加GPU间隔标注
            if i < gpu_count - 1:
                self.add_dimension_annotation(ax, gpu_x + gpu_width_size,
                                             gpu_slot_start_y - gpu_height_size/2,
                                             gpu_spacing, "2mm", 'horizontal', offset=-1.5)
        '''
        # 设置坐标范围
        ax.set_xlim(0, cabinet_width)
        ax.set_ylim(cabinet_height - gpu_array_top - gpu_array_height - 1,
                   cabinet_height + 1)
        ax.set_title("GPU机箱布局", fontsize=14, color='#1e40af', fontweight='bold')
        ax.grid(True, linestyle='--', alpha=0.3)

        self.model_canvas.draw()

    def add_dimension_annotation(self, ax, x, y, length, text, orientation='horizontal', offset=0):
        """添加尺寸标注到图形"""
        if orientation == 'horizontal':
            # 水平尺寸线
            ax.annotate('',
                        xy=(x, y + offset),
                        xytext=(x + length, y + offset),
                        arrowprops=dict(arrowstyle="|-|", color='#4b5563', linewidth=0.8))
            # 文本标注
            ax.text(x + length/2, y + offset + 0.2, text,
                    ha='center', va='bottom', fontsize=8, color='#4b5563')
        else:  # vertical
            # 垂直尺寸线
            ax.annotate('',
                        xy=(x + offset, y),
                        xytext=(x + offset, y + length),
                        arrowprops=dict(arrowstyle="|-|", color='#4b5563', linewidth=0.8))
            # 文本标注
            ax.text(x + offset + 0.3, y + length/2, text,
                    ha='left', va='center', rotation=90, fontsize=8, color='#4b5563')

    def setup_styles(self):
        """设置UI样式，解决中文显示问题"""
        # 设置全局字体
        app = QApplication.instance()
        if app is not None:
            system = platform.system()
            if system == 'Windows':
                font = QFont("Microsoft YaHei", 9)
            elif system == 'Darwin':  # macOS
                font = QFont("PingFang SC", 12)
            else:  # Linux
                font = QFont("WenQuanYi Micro Hei", 10)
            app.setFont(font)

        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f7fa;
            }
            QGroupBox {
                border: 1px solid #d1d5db;
                border-radius: 8px;
                margin-top: 1.5ex;
                padding-top: 12px;
                background-color: #ffffff;
                font-weight: bold;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top left;
                padding: 0 8px;
                background-color: transparent;
                color: #1e40af;
            }
            QPushButton {
                background-color: #3b82f6;
                color: white;
                border-radius: 6px;
                padding: 8px 16px;
                font: bold 10pt;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #2563eb;
            }
            QPushButton:pressed {
                background-color: #1d4ed8;
            }
            QLineEdit, QComboBox, QSpinBox {
                border: 1px solid #d1d5db;
                border-radius: 4px;
                padding: 6px;
                background-color: #f9fafb;
            }
            QTabWidget::pane {
                border: 1px solid #d1d5db;
                border-radius: 6px;
                background: white;
            }
            QTabBar::tab {
                background: #e5e7eb;
                border: 1px solid #d1d5db;
                border-bottom: none;
                border-top-left-radius: 6px;
                border-top-right-radius: 6px;
                padding: 8px 16px;
                margin-right: 2px;
                font: 10pt;
            }
            QTabBar::tab:selected {
                background: white;
                border-bottom: 2px solid #3b82f6;
                font-weight: bold;
            }
            QProgressBar {
                border: 1px solid #d1d5db;
                border-radius: 4px;
                text-align: center;
                background-color: #f9fafb;
            }
            QProgressBar::chunk {
                background-color: #3b82f6;
                width: 10px;
            }
            QTableWidget {
                border: 1px solid #d1d5db;
                border-radius: 6px;
                background-color: white;
                gridline-color: #e5e7eb;
            }
            QHeaderView::section {
                background-color: #eff6ff;
                padding: 6px;
                border: none;
                font-weight: bold;
            }
            QCheckBox::indicator {
                width: 20px;
                height: 20px;
            }
        """)

    def setup_connections(self):
        """设置信号连接"""
        self.run_button.clicked.connect(self.run_simulation)
        self.export_button.clicked.connect(self.export_results)

        # 当任何一个复选框状态变化时更新GPU数量和模型
        for checkbox in self.slot_checkboxes:
            checkbox.stateChanged.connect(self.update_gpu_config)

    def update_gpu_config(self):
        """更新GPU配置"""
        # 计算选中的GPU数量
        selected_count = sum(1 for checkbox in self.slot_checkboxes if checkbox.isChecked())
        self.gpu_count_label.setText(f"已安装GPU数量: {selected_count}")

        # 更新模型图
        self.draw_model()

    def run_simulation(self):
        """执行仿真逻辑"""
        try:
            # 重置进度条
            self.progress_bar.setValue(0)
            self.progress_bar.setFormat("准备仿真...")

            # 获取参数
            inlet_vel = float(self.inlet_velocity.text())
            inlet_temp = float(self.inlet_temp.text())
            cpu_power = float(self.cpu_power.text())
            gpu_power = float(self.gpu_power.text())

            # 获取GPU配置
            selected_slots = [i+1 for i, cb in enumerate(self.slot_checkboxes) if cb.isChecked()]

            # 切换到结果标签页
            self.tab_widget.setCurrentIndex(1)

            # 初始化仿真数据基本信息
            self.simulation_data = {
                "inlet_velocity": inlet_vel,
                "inlet_temp": inlet_temp,
                "cpu_power": cpu_power,
                "gpu_power": gpu_power,
                "gpu_slots": selected_slots,
                "gpu_count": len(selected_slots),
                "algorithm": self.algo_combo.currentText(),
                "temperatures": {},
                "gpu_exhaust_velocity": 0.2,
                "exhaust_temp": 70,
                "ignore_heat_interaction": True,
                "flow_data": None
            }

            # 创建求解器实例
            mesh = RectangularMesh(50, 50)
            solver = CFDSolver(mesh)

            # 设置边界条件
            gpu_positions = [i for i, cb in enumerate(self.slot_checkboxes) if cb.isChecked()]
            solver.set_boundary_conditions(
                inlet_vel=float(self.inlet_velocity.text()),
                inlet_temp=float(self.inlet_temp.text()),
                gpu_power=float(self.gpu_power.text()),
                gpu_positions=gpu_positions
            )

            # 显示进度
            self.progress_bar.setValue(25)
            self.progress_bar.setFormat("求解动量方程... 25%")
            QApplication.processEvents()

            # 执行求解
            residuals = solver.solve(algorithm=self.algo_combo.currentText())

            print("求解结束：", residuals)

            # 进度更新
            self.progress_bar.setValue(75)
            self.progress_bar.setFormat("处理结果数据... 75%")
            QApplication.processEvents()

            # 记录流场结果
            self.simulation_data.update({
                "flow_data": (solver.u, solver.v, solver.p, solver.T),
                "residuals": residuals
            })

            # 根据计算结果生成温度数据
            # 将开尔文温度转换为摄氏度
            T_celsius = solver.T - 273.15

            # CPU温度 - 从温度场中提取CPU区域的平均温度
            cpu_region_1 = T_celsius[15:25, 35:45]  # 假设CPU1的位置
            cpu_region_2 = T_celsius[15:25, 25:35]  # 假设CPU2的位置
            self.simulation_data["temperatures"]["CPU散热器1"] = np.mean(cpu_region_1)
            self.simulation_data["temperatures"]["CPU散热器2"] = np.mean(cpu_region_2)

            # GPU温度 - 从温度场中提取每个GPU位置的温度
            gpu_height = 5  # GPU在网格中的高度范围
            for slot, pos in enumerate(gpu_positions):
                x_start = int(0.3 * mesh.nx) + pos * 5  # GPU在x方向的起始位置
                x_end = x_start + 3  # GPU宽度
                y_start = int(0.6 * mesh.ny)  # GPU在y方向的起始位置
                y_end = y_start + gpu_height

                gpu_region = T_celsius[x_start:x_end, y_start:y_end]
                self.simulation_data["temperatures"][f"GPU{slot+1}"] = np.mean(gpu_region)

            # 出口温度 - 使用底部区域的平均温度
            exhaust_region = T_celsius[:, 0:5]  # 底部5行作为出口区域
            self.simulation_data["exhaust_temp"] = np.mean(exhaust_region)

            # 环境温度 - 使用入口温度
            self.simulation_data["temperatures"]["环境"] = inlet_temp - 273.15

            # 更新进度
            self.progress_bar.setValue(95)
            self.progress_bar.setFormat("完成仿真... 95%")
            QApplication.processEvents()

            print("仿真数据：", self.simulation_data)

            # 显示结果
            self.show_results()

        except ValueError as e:
            print("错误：", e)
            self.progress_bar.setFormat(f"错误: {str(e)}")

    def show_results(self):
        """显示仿真结果"""
        # 绘制结果图
        self.draw_results()

        # 更新温度数据表
        self.update_temp_table()

        # 切换到结果标签页
        self.tab_widget.setCurrentIndex(1)
        self.progress_bar.setFormat("仿真完成! 出口温度:70℃")

    def draw_results(self):
        """绘制仿真结果图"""
        if not self.simulation_data.get("flow_data"):
            return

        fig = self.result_canvas.figure
        fig.clear()

        # 获取流场数据
        u, v, p, T = self.simulation_data["flow_data"]

        # 将温度转换为摄氏度
        T_celsius = T - 273.15

        # 创建网格点
        nx, ny = T.shape
        x = np.linspace(0, 0.42, nx)  # 42cm = 0.42m
        y = np.linspace(0, 0.69, ny)  # 69cm = 0.69m
        X, Y = np.meshgrid(x, y)

        # 设置中文标题
        try:
            fig.suptitle('GPU机箱流场仿真结果', fontsize=16, fontweight='bold')
        except:
            fig.suptitle('GPU Enclosure Flow Simulation Results', fontsize=16, fontweight='bold')

        # 创建子图
        ax1 = fig.add_subplot(211)
        ax2 = fig.add_subplot(212)

        # 绘制温度场
        temp_contour = ax1.contourf(X, Y, T_celsius.T, levels=20, cmap='RdYlBu_r')
        fig.colorbar(temp_contour, ax=ax1, label='温度 (℃)')
        ax1.set_title('温度分布', fontsize=12)
        ax1.set_xlabel('宽度 (m)')
        ax1.set_ylabel('高度 (m)')

        # 添加机箱结构标注
        # 1. 左下角电源区域（10x35cm）
        power_supply = Rectangle((0, 0), 0.10, 0.35,
                               fill=True, facecolor='gray', alpha=0.3,
                               edgecolor='black', linestyle='-')
        ax1.add_patch(power_supply)
        ax1.text(0.05, 0.175, '电源\n区域', ha='center', va='center')

        # 2. CPU散热器
        cpu_left = Rectangle((0.06, 0.60), 0.09, 0.07, fill=False, edgecolor='red', linestyle='--')
        cpu_right = Rectangle((0.27, 0.60), 0.09, 0.07, fill=False, edgecolor='red', linestyle='--')
        ax1.add_patch(cpu_left)
        ax1.add_patch(cpu_right)

        # 3. GPU阵列
        selected_slots = self.simulation_data.get("gpu_slots", [])
        for slot in selected_slots:
            x_start = 0.10 + 0.036 + (slot-1) * (0.02 + 0.002)  # 左边界3.6cm + GPU间隔
            gpu = Rectangle((x_start, 0.04), 0.02, 0.28,
                          fill=False, edgecolor='blue', linestyle='-')
            ax1.add_patch(gpu)

        # 添加边界条件标注
        ax1.annotate('冷气入口', xy=(0.21, 0.69), xytext=(0.21, 0.65),
                    arrowprops=dict(arrowstyle='->'), ha='center')
        ax1.annotate('热气出口\n(70°C, 0.2m/s)', xy=(0.21, 0), xytext=(0.21, 0.1),
                    arrowprops=dict(arrowstyle='->'), ha='center')

        # 处理错位网格的速度场
        # 确保速度场尺寸匹配
        u_interp = np.zeros_like(T[:-1, :-1])
        v_interp = np.zeros_like(T[:-1, :-1])

        # 对速度场进行插值，注意边界处理
        for i in range(u_interp.shape[0]):
            for j in range(u_interp.shape[1]):
                # 检查是否在边界
                if i < u.shape[0]-1 and j < u.shape[1]-1:
                    u_interp[i,j] = 0.25 * (u[i,j] + u[i,j+1] + u[i+1,j] + u[i+1,j+1])
                else:
                    # 边界处使用可用的值
                    if i == u.shape[0]-1 and j < u.shape[1]-1:
                        u_interp[i,j] = 0.5 * (u[i,j] + u[i,j+1])
                    elif i < u.shape[0]-1 and j == u.shape[1]-1:
                        u_interp[i,j] = 0.5 * (u[i,j] + u[i+1,j])
                    else:
                        u_interp[i,j] = u[i,j]

                if i < v.shape[0]-1 and j < v.shape[1]-1:
                    v_interp[i,j] = 0.25 * (v[i,j] + v[i,j+1] + v[i+1,j] + v[i+1,j+1])
                else:
                    # 边界处使用可用的值
                    if i == v.shape[0]-1 and j < v.shape[1]-1:
                        v_interp[i,j] = 0.5 * (v[i,j] + v[i,j+1])
                    elif i < v.shape[0]-1 and j == v.shape[1]-1:
                        v_interp[i,j] = 0.5 * (v[i,j] + v[i+1,j])
                    else:
                        v_interp[i,j] = v[i,j]

        # 计算速度场大小
        velocity_magnitude = np.sqrt(u_interp**2 + v_interp**2)

        # 创建速度场网格点
        nx_v, ny_v = velocity_magnitude.shape
        x_v = np.linspace(0, 0.42, nx_v)
        y_v = np.linspace(0, 0.69, ny_v)
        X_v, Y_v = np.meshgrid(x_v, y_v)

        # 绘制流场
        # 降采样以使箭头更清晰
        skip = 3
        ax2.quiver(X_v[::skip, ::skip], Y_v[::skip, ::skip],
                  u_interp[::skip, ::skip].T, v_interp[::skip, ::skip].T,
                  velocity_magnitude[::skip, ::skip].T,
                  cmap='viridis',
                  scale=30)

        # 绘制速度场等值线
        vel_contour = ax2.contourf(X_v, Y_v, velocity_magnitude.T, levels=20, cmap='viridis', alpha=0.3)
        fig.colorbar(vel_contour, ax=ax2, label='速度 (m/s)')

        # 在流场图上也添加机箱结构
        # 1. 左下角电源区域
        power_supply2 = Rectangle((0, 0), 0.10, 0.35,
                                fill=True, facecolor='gray', alpha=0.3,
                                edgecolor='black', linestyle='-')
        ax2.add_patch(power_supply2)
        ax2.text(0.05, 0.175, '电源\n区域', ha='center', va='center')

        # 2. CPU散热器
        ax2.add_patch(Rectangle((0.06, 0.60), 0.09, 0.07, fill=False, edgecolor='red', linestyle='--'))
        ax2.add_patch(Rectangle((0.27, 0.60), 0.09, 0.07, fill=False, edgecolor='red', linestyle='--'))

        # 3. GPU阵列
        for slot in selected_slots:
            x_start = 0.10 + 0.036 + (slot-1) * (0.02 + 0.002)
            ax2.add_patch(Rectangle((x_start, 0.04), 0.02, 0.28,
                                  fill=False, edgecolor='blue', linestyle='-'))

        ax2.set_title('流速分布', fontsize=12)
        ax2.set_xlabel('宽度 (m)')
        ax2.set_ylabel('高度 (m)')

        # 调整布局
        fig.tight_layout(rect=[0, 0, 1, 0.96])

        self.result_canvas.draw()

    def update_temp_table(self):
        """更新温度数据表"""
        temperatures = self.simulation_data["temperatures"]
        self.temp_table.setRowCount(len(temperatures) + 1)

        # 添加表头
        self.temp_table.setHorizontalHeaderLabels(["组件", "位置", "温度(℃)", "状态"])

        # 添加数据行
        row = 0
        max_temp = 0
        max_temp_component = ""

        # CPU1
        self.temp_table.setItem(row, 0, QTableWidgetItem("CPU散热器1"))
        self.temp_table.setItem(row, 1, QTableWidgetItem("左侧"))
        self.temp_table.setItem(row, 2, QTableWidgetItem(f"{temperatures['CPU散热器1']:.1f}"))
        row += 1

        # CPU2
        self.temp_table.setItem(row, 0, QTableWidgetItem("CPU散热器2"))
        self.temp_table.setItem(row, 1, QTableWidgetItem("右侧"))
        self.temp_table.setItem(row, 2, QTableWidgetItem(f"{temperatures['CPU散热器2']:.1f}"))
        row += 1

        # GPU - 只显示已安装的GPU
        for slot in self.simulation_data["gpu_slots"]:
            component = f"GPU{slot}"
            location = f"槽位{slot}"
            self.temp_table.setItem(row, 0, QTableWidgetItem(component))
            self.temp_table.setItem(row, 1, QTableWidgetItem(location))
            temp_val = temperatures.get(component, 0)
            self.temp_table.setItem(row, 2, QTableWidgetItem(f"{temp_val:.1f}"))

            # 温度状态评估
            status = ""
            if temp_val > 85:
                status = "危险"
                color = QColor(220, 53, 69)  # 红色
            elif temp_val > 75:
                status = "警告"
                color = QColor(255, 193, 7)  # 黄色
            else:
                status = "正常"
                color = QColor(40, 167, 69)  # 绿色

            status_item = QTableWidgetItem(status)
            status_item.setForeground(color)
            self.temp_table.setItem(row, 3, status_item)

            # 记录最高温度
            if temp_val > max_temp:
                max_temp = temp_val
                max_temp_component = component

            row += 1

        # 环境温度
        self.temp_table.setItem(row, 0, QTableWidgetItem("环境"))
        self.temp_table.setItem(row, 1, QTableWidgetItem("外部"))
        self.temp_table.setItem(row, 2, QTableWidgetItem(f"{temperatures['环境']:.1f}"))
        status_item = QTableWidgetItem("正常")
        status_item.setForeground(QColor(40, 167, 69))
        self.temp_table.setItem(row, 3, status_item)
        row += 1

        # 出口温度
        self.temp_table.setItem(row, 0, QTableWidgetItem("出口"))
        self.temp_table.setItem(row, 1, QTableWidgetItem("底部"))
        self.temp_table.setItem(row, 2, QTableWidgetItem(f"{self.simulation_data['exhaust_temp']:.1f}"))
        status_item = QTableWidgetItem("设计值")
        status_item.setForeground(QColor(107, 114, 128))
        self.temp_table.setItem(row, 3, status_item)
        row += 1

        # 添加最高温度行
        self.temp_table.setItem(row, 0, QTableWidgetItem("最高温度"))
        self.temp_table.setItem(row, 1, QTableWidgetItem(""))
        self.temp_table.setItem(row, 2, QTableWidgetItem(f"{max_temp:.1f}"))
        status_item = QTableWidgetItem(f"({max_temp_component})")
        status_item.setForeground(QColor(33, 37, 41))
        self.temp_table.setItem(row, 3, status_item)

        # 设置最高温度行样式
        for col in range(4):
            item = self.temp_table.item(row, col)
            if item:
                item.setBackground(QColor(233, 236, 239))
                font = item.font()
                font.setBold(True)
                item.setFont(font)

    def export_results(self):
        """导出结果逻辑"""
        self.progress_bar.setFormat("正在导出结果...")
        QApplication.processEvents()

        # 模拟导出过程
        time.sleep(1.5)

        # 生成报告
        report = self.generate_report()

        # 在实际应用中，这里会保存为PDF文件
        print("仿真报告已生成:")
        print(report)

        self.progress_bar.setFormat("导出成功! 结果已保存为report.pdf")

    def generate_report(self):
        """生成仿真报告"""
        report = f"""
        ======================
        GPU机箱流场仿真报告 (精确布局)
        ======================

        仿真时间: {time.strftime("%Y-%m-%d %H:%M:%S")}

        [布局参数]
        1. GPU阵列区域尺寸: 32cm×35cm
        2. 左边界右移: 10cm
        3. GPU槽位起始位置: 距左边界3.6cm
        4. GPU间隔: 2mm
        5. 插槽距阵列顶部: 3cm
        6. 出风口高度: 4cm

        [设备配置]
        • 机箱尺寸: 42cm x 69cm
        • 风扇区域: 顶部冷空气入口
        • CPU散热器: 两个 (尺寸: 9cm x 7cm)
        • GPU阵列: 8槽位
        • 出口区域: 底部

        [物理参数]
        入口速度: {self.simulation_data['inlet_velocity']} m/s
        入口温度: {self.simulation_data['inlet_temp']} K
        CPU功率: {self.simulation_data['cpu_power']} W
        GPU功率: {self.simulation_data['gpu_power']} W
        求解算法: {self.simulation_data['algorithm']}

        [温度数据]
        """

        # 添加温度数据
        max_temp = 0
        for component, temp in self.simulation_data["temperatures"].items():
            report += f"{component}: {temp:.1f} ℃\n"
            if temp > max_temp:
                max_temp = temp

        report += f"出口温度: {self.simulation_data['exhaust_temp']} ℃\n"
        report += f"\n最高温度: {max_temp:.1f} ℃\n"

        # 添加分析结论
        report += """

        [分析结论]
        1. GPU阵列精确布局实现成功
        2. 左侧边界右移10cm节省空间
        3. 3.6cm起始位置确保合理散热间隙
        4. 底部出风口4cm高度设计合理
        5. 出口温度达到70℃设计值

        [优化建议]
        • 在高温GPU槽位增加辅助散热
        • 优化风扇转速分布
        • 考虑在热区槽位使用导热性能更好的材料
        """

        return report

if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 设置应用程序全局字体
    system = platform.system()
    font = QFont("Microsoft YaHei", 9)
    app.setFont(font)

    window = SimulationSystem()
    window.show()
    sys.exit(app.exec_())